package com.enroban.dr.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;

/**
 * Zip文件工具类
 * @author Luxh
 */
public class ZipFileUtil {

    /**
     * 把文件压缩成zip格式
     *
     * @param files       需要压缩的文件
     * @param zipFilePath 压缩后的zip文件路径   ,如"D:/test/aa.zip";
     */
    public static void compressFiles2Zip(File[] files, String zipFilePath) {
        if (files != null && files.length > 0) {
            ZipArchiveOutputStream zaos = null;
            try {
                File zipFile = new File(zipFilePath);
                zaos = new ZipArchiveOutputStream(zipFile);
                //Use Zip64 extensions for all entries where they are required
                zaos.setUseZip64(Zip64Mode.AsNeeded);

                //将每个文件用ZipArchiveEntry封装
                //再用ZipArchiveOutputStream写到压缩文件中
                for (File file : files) {
                    if (file != null) {
                        ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(file, file.getName());
                        zaos.putArchiveEntry(zipArchiveEntry);
                        InputStream is = null;
                        try {
                            is = new BufferedInputStream(new FileInputStream(file));
                            byte[] buffer = new byte[1024 * 5];
                            int len = -1;
                            while ((len = is.read(buffer)) != -1) {
                                //把缓冲区的字节写入到ZipArchiveEntry
                                zaos.write(buffer, 0, len);
                            }
                            //Writes all necessary data for this entry.
                            zaos.closeArchiveEntry();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        } finally {
                            if (is != null)
                                is.close();
                        }

                    }
                }
                zaos.finish();
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    if (zaos != null) {
                        zaos.close();
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

        }

    }

    /**
     * 把zip文件解压到指定的文件夹
     *
     * @param zipFilePath zip文件路径, 如 "D:/test/aa.zip"
     * @param saveFileDir 解压后的文件存放路径, 如"D:/test/"
     */
//    public static void decompressZip(String zipFilePath, String saveFileDir) {
//        File file = new File(zipFilePath);
//        if (file.exists()) {
//            InputStream is = null;
//            //can read Zip archives
//            ZipArchiveInputStream zais = null;
//            try {
//                is = new FileInputStream(file);
//                zais = new ZipArchiveInputStream(is);
//                ArchiveEntry archiveEntry = null;
//                //把zip包中的每个文件读取出来
//                //然后把文件写到指定的文件夹
//                while ((archiveEntry = zais.getNextEntry()) != null) {
//                    //获取文件名
//                    String entryFileName = archiveEntry.getName();
//                    //构造解压出来的文件存放路径
//                    String entryFilePath = saveFileDir + entryFileName;
//                    byte[] content = new byte[(int) archiveEntry.getSize()];
//                    zais.read(content);
//                    OutputStream os = null;
//                    try {
//                        //把解压出来的文件写到指定路径
//                        File entryFile = new File(entryFilePath);
//                        os = new BufferedOutputStream(new FileOutputStream(entryFile));
//                        os.write(content);
//                    } catch (IOException e) {
//                        e.printStackTrace();
////                        throw new IOException(e);
//                    } finally {
//                        if (os != null) {
//                            os.flush();
//                            os.close();
//                        }
//                    }
//
//                }
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            } finally {
//                try {
//                    if (zais != null) {
//                        zais.close();
//                    }
//                    if (is != null) {
//                        is.close();
//                    }
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            }
//        }
//
//    }

    /**
     * 将 zip 压缩包解压成文件到指定文件夹下
     * @param zipFile    待解压的压缩文件。亲测  .zip 文件有效；.7z 压缩解压时抛异常。
     * @param targetDir  解压后文件存放的目的地. 此目录必须存在，否则异常。
     * @return
     */
    public static boolean decompressZip2Files(String zipFile, String targetDir) {
        return decompressZip2Files(new File(zipFile),new File(targetDir));
    }

    /**
     * 将 zip 压缩包解压成文件到指定文件夹下
     *
     * @param zipFile   待解压的压缩文件。亲测  .zip 文件有效；.7z 压缩解压时抛异常。
     * @param targetDir 解压后文件存放的目的地. 此目录必须存在，否则异常。
     * @return 是否成功
     */
    public static boolean decompressZip2Files(File zipFile, File targetDir) {
        InputStream inputStream = null;//源文件输入流，用于构建 ZipArchiveInputStream
        OutputStream outputStream = null;//解压缩的文件输出流
        ZipArchiveInputStream zipArchiveInputStream = null;//zip 文件输入流
        ArchiveEntry archiveEntry = null;//压缩文件实体.
        try {
            inputStream = new FileInputStream(zipFile);//创建输入流，然后转压缩文件输入流
            zipArchiveInputStream = new ZipArchiveInputStream(inputStream, "UTF-8");
            //遍历解压每一个文件.
            while (null != (archiveEntry = zipArchiveInputStream.getNextEntry())) {
                String archiveEntryFileName = archiveEntry.getName();//获取文件名
//                System.out.println(archiveEntryFileName);
                if(archiveEntry.isDirectory()){ // 如果是文件夹就创建
                    File dir = new File(targetDir, archiveEntryFileName);
                    dir.mkdir();
                    continue;
                }
                File entryFile = new File(targetDir, archiveEntryFileName);//把解压出来的文件写到指定路径
                byte[] buffer = new byte[1024 * 5];
                outputStream = new FileOutputStream(entryFile);
                int length = -1;
                while ((length = zipArchiveInputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, length);
                }
                outputStream.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (null != outputStream) {
                    outputStream.close();
                }
                if (null != zipArchiveInputStream) {
                    zipArchiveInputStream.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }


}
